package wavedigest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import wavedigest.data.EmailRegistration;
import wavedigest.data.PMF;
import wavedigest.data.RegisteredWave;
import wavedigest.data.WaveChange;

@SuppressWarnings("serial")
public class UpdateServlet extends HttpServlet
{
	private static Logger log = Logger.getLogger(UpdateServlet.class.getName());
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
	{
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
	{
		String requestPath = req.getRequestURI();
		log.info("request on update servlet: " + requestPath);
		
		int scheduleType = -1;
		if (requestPath.equals("/hourly"))
		{
			scheduleType = EmailRegistration.SCHEDULE_TYPE_HOURLY;
		}
		else if (requestPath.equals("/daily"))
		{
			scheduleType = EmailRegistration.SCHEDULE_TYPE_DAILY;
		}
		else if (requestPath.equals("/weekly"))
		{
			scheduleType = EmailRegistration.SCHEDULE_TYPE_WEEKLY;
		}
		else
			return;
		
		sendUpdates(scheduleType);
	}

	@SuppressWarnings("unchecked")
	private void sendUpdates(int scheduleType)
	{
		log.info("sending updates for scheduleType " + scheduleType);
		
		Calendar calendar = new GregorianCalendar();
		switch (scheduleType)
		{
			case EmailRegistration.SCHEDULE_TYPE_HOURLY:
				calendar.add(Calendar.HOUR, -1);
				calendar.set(Calendar.MINUTE, 0);
				break;
			case EmailRegistration.SCHEDULE_TYPE_DAILY:
				calendar.add(Calendar.DAY_OF_MONTH, -1);
				calendar.set(Calendar.HOUR, 0);
				calendar.set(Calendar.MINUTE, 0);
				break;
			case EmailRegistration.SCHEDULE_TYPE_WEEKLY:
				calendar.add(Calendar.WEEK_OF_YEAR, -1);
				calendar.set(Calendar.DAY_OF_WEEK, 0);
				calendar.set(Calendar.HOUR, 0);
				calendar.set(Calendar.MINUTE, 0);
				break;
			default:
				return;
		}
		
		Date oldestDate = calendar.getTime();
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try
		{
			// send updates
			String query = "select from " + RegisteredWave.class.getName();
			List<RegisteredWave> waveList = (List<RegisteredWave>) pm.newQuery(query).execute();
			if (null == waveList)
				return;

			for (RegisteredWave wave : waveList)
			{
				// get changes
				List<WaveChange> applicableChanges = new ArrayList<WaveChange>();
				for (WaveChange change : wave.getChanges())
				{
					if (change.getChangeTime().compareTo(oldestDate) >= 0)
					{
						log.info("applicable change: " + change.getChangeTime() + " >= " + oldestDate);
						applicableChanges.add(change);
					}
				}
				
				if (applicableChanges.size() > 0)
				{
					for (EmailRegistration registration : wave.getRegistrations())
					{
						if (registration.getScheduleType() == scheduleType)
							sendUpdateEmail(wave.getWaveID(), registration, applicableChanges);
					}
				}
			}	
		}
		finally
		{
			pm.close();
		}
	}

	private void sendUpdateEmail(String waveID, EmailRegistration registration, List<WaveChange> applicableChanges)
	{
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		try
		{
			log.info("Sending update email: waveid=" + waveID + ", email=" + registration.getEmailAddress());
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("adam.schepis@gmail.com", "WaveDigest Updates"));
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(registration.getEmailAddress()));
			msg.setSubject("Update to wave" + waveID);
			
			StringBuilder body = new StringBuilder();
			for (WaveChange change : applicableChanges)
			{
				body.append("Modified By: " + change.getModifiedBy() + "\n\n");
				body.append("Modified At: " + change.getChangeTime() + "\n\n");
				body.append(change.getChangeDescription());
				body.append("\n\n--------------------------------------------------\n\n");
			}
			
			msg.setText(body.toString());
			Transport.send(msg);
		}
		catch (Exception e1)
		{
			log.log(Level.SEVERE, "Error sending mail: ", e1);
		}
	}
}
